#include "elslider.h"
#include <QApplication>
#include <QPaintEvent>
#include <QPainter>
#include <QPropertyAnimation>
#include "eltheme.h"
#include "eltooltip.h"

ElSlider::ElSlider(QWidget *parent)
    : ElComponent{parent}
{
    resize(200, 80);
    setCursor(Qt::PointingHandCursor);
    sliderCircle = new ElSliderCircle(this);
    initPalette();
}

int ElSlider::min() const
{
    return _min;
}

void ElSlider::setMin(int min)
{
    if (_min == min)
        return;
    _min = min;
}

int ElSlider::max() const
{
    return _max;
}

void ElSlider::setMax(int max)
{
    if (_max == max)
        return;
    _max = max;
}

int ElSlider::value() const
{
    return _value;
}

void ElSlider::setValue(int value)
{
    if (_value == value || value < _min || value > _max)
        return;
    _value = value;
    emit valueChanged(_value);
    update();
    sliderCircle->updateTooltip(_value);
}

void ElSlider::setTooltip(ElTooltip *tooltip)
{
    sliderCircle->setTooltip(tooltip);
}

ElTooltip *ElSlider::tooltip() const
{
    return sliderCircle->tooltip();
}

bool ElSlider::event(QEvent *e)
{
    if (e->type() == QEvent::EnabledChange) {
        sliderCircle->setEnabled(isEnabled());
        _palette.toggleColorGroup(isEnabled() ? ElPalette::Normal : ElPalette::Disabled);
        update();
    }
    return ElComponent::event(e);
}

void ElSlider::paintEvent(QPaintEvent *e)
{
    QPainter painter(this);
    painter.setBrush(_palette.color(ElPalette::Background));
    painter.setPen(QColor(228, 231, 237));
    qreal y = (height() - Slider_Height) / 2;
    qreal padding_lr = sliderCircle->radius() - 1;
    auto slider_rect = QRectF(padding_lr, y, width() - 2 * padding_lr, Slider_Height);
    painter.drawRoundedRect(slider_rect, Slider_Height / 2, Slider_Height / 2);
    auto r = sliderCircle->rect();
    qreal progress = padding_lr + _value / (qreal) _max * width();
    r.moveCenter(QPoint(progress, height() / 2));
    sliderCircle->move(r.topLeft());
    sliderCircle->raise();
    painter.setBrush(_palette.color(ElPalette::Foreground));
    painter.drawRoundedRect(padding_lr,
                            y,
                            progress,
                            Slider_Height,
                            Slider_Height / 2,
                            Slider_Height / 2);
    e->accept();
}

void ElSlider::mousePressEvent(QMouseEvent *e)
{
    if (!isEnabled()) {
        e->ignore();
        return;
    }
    setValue(e->pos().x() * _max / width());
    emit sliderPressed();
    e->accept();
}

void ElSlider::initPalette()
{
    _palette.setColor(ElPalette::Background, QColor(228, 231, 237));
    _palette.setColor(ElPalette::Foreground, ThemeColor::primaryColor);
    _palette.setColor(ElPalette::Disabled, ElPalette::Background, QColor(192, 196, 204));
    _palette.setColor(ElPalette::Disabled, ElPalette::Foreground, QColor(192, 196, 204));
}

const qreal ElSlider::ElSliderCircle::Init_Radius = 7;

qreal ElSlider::Slider_Height = 8;

ElSlider::ElSliderCircle::ElSliderCircle(ElSlider *parent)
    : ElComponent{parent}
{
    _slider = parent;
    setAttribute(Qt::WA_Hover);
    setCursor(Qt::OpenHandCursor);
    _animation = new QPropertyAnimation(this, "geometry", this);
    _animation->setDuration(1200);
    _animation->setEasingCurve(QEasingCurve::OutQuad);
    auto tooltip = new ElTooltip(_slider);
    tooltip->setPlacement(ElTooltip::Top);
    setTooltip(tooltip);
    initPalette();
}

void ElSlider::ElSliderCircle::updateTooltip(int value)
{
    _tooltip->setContent(QString::number(value));
    _tooltip->update();
}

bool ElSlider::ElSliderCircle::event(QEvent *e)
{
    if (e->type() == QEvent::EnabledChange) {
        _palette.toggleColorGroup(isEnabled() ? ElPalette::Normal : ElPalette::Disabled);
        update();
    }
    return ElComponent::event(e);
}

void ElSlider::ElSliderCircle::paintEvent(QPaintEvent *e)
{
    resize(2.5 * _radius, 2.5 * _radius);
    QPainter painter(this);
    painter.setBrush(Qt::white);
    QPen pen;
    pen.setCapStyle(Qt::RoundCap);
    pen.setJoinStyle(Qt::RoundJoin);
    pen.setWidthF(1.5);
    pen.setColor(_palette.color(ElPalette::Border));
    painter.setPen(pen);
    QRectF _rectf(this->rect());
    painter.drawEllipse(_rectf.center(), _radius, _radius);
    e->accept();
}

void ElSlider::ElSliderCircle::enterEvent(QEvent *e)
{
    if (!isEnabled()) {
        e->ignore();
        return;
    }
    showTooltip();
    // _animation->setStartValue(geometry());
    _radius = Init_Radius + 1; // WA_Hover is set so the widget updates automatically
    // _animation->setEndValue(geometry());
    // _animation->start();
    e->accept();
}

void ElSlider::ElSliderCircle::leaveEvent(QEvent *e)
{
    if (!isEnabled()) {
        e->ignore();
        return;
    }
    hideTooltip();
    // _animation->setStartValue(geometry());
    _radius = Init_Radius; // WA_Hover is set so the widget updates automatically
    // _animation->setEndValue(geometry());
    // _animation->start();
    e->accept();
}

void ElSlider::ElSliderCircle::mousePressEvent(QMouseEvent *e)
{
    if (!isEnabled()) {
        e->ignore();
        return;
    }
    setCursor(Qt::ClosedHandCursor);
    emit _slider->sliderPressed();
    e->accept();
}

void ElSlider::ElSliderCircle::mouseReleaseEvent(QMouseEvent *e)
{
    if (!isEnabled()) {
        e->ignore();
        return;
    }
    setCursor(Qt::OpenHandCursor);
    emit _slider->sliderReleased();
    e->accept();
}

void ElSlider::ElSliderCircle::mouseMoveEvent(QMouseEvent *e)
{
    if (!isEnabled()) {
        e->ignore();
        return;
    }
    auto pos = mapToParent(e->pos()); // position related to its parent, ElSlider
    if (pos.x() < Init_Radius || pos.x() > _slider->width() - 2 * Init_Radius) {
        e->ignore();
        return;
    }
    _slider->setValue(pos.x() * _slider->max() / _slider->width());
    emit _slider->sliderMoved();
    e->accept();
}

void ElSlider::ElSliderCircle::initPalette()
{
    _palette.setColor(ElPalette::Border, ThemeColor::primaryColor);
    _palette.setColor(ElPalette::Disabled, ElPalette::Border, QColor(192, 196, 204));
}

bool ElSlider::ElSliderCircle::isStepStop() const
{
    return _stepStop;
}

void ElSlider::ElSliderCircle::setStepStop(bool stepStop)
{
    if (_stepStop == stepStop)
        return;
    _stepStop = stepStop;
    update();
}

qreal ElSlider::ElSliderCircle::radius() const
{
    return _radius;
}

void ElSlider::ElSliderCircle::setRadius(qreal radius)
{
    if (qFuzzyCompare(_radius, radius))
        return;
    _radius = radius;
    update();
}
